package com.recharge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.recharge.common.domain.PageDO;
import com.recharge.common.enums.ErrorCode;
import com.recharge.common.result.ResultDO;
import com.recharge.common.result.ResultSupport;
import com.recharge.common.util.BeanUtilsExtends;

import com.recharge.common.util.Constant;
import com.recharge.common.util.http.MapTool;
import com.recharge.core.entity.GoodsGroupEntity;
import com.recharge.core.entity.RouteFilterEntity;

import com.recharge.core.entity.RouteFilterMerchantEntity;
import com.recharge.core.mapper.RouteFilterMapper;
import com.recharge.core.mapper.RouteFilterMerchantMapper;
import com.recharge.domain.query.RouteFilterQueryDO;
import com.recharge.domain.vo.GoodsGroupDO;
import com.recharge.domain.vo.RouteFilterDO;
import com.recharge.domain.vo.RouteFilterMerchantDO;

import com.recharge.domain.vo.UserDO;
import com.recharge.service.RouteFilterMerchantService;
import com.recharge.service.RouteFilterService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;

import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Reagan
 * @since 2020-09-21
 */
@Service
public class RouteFilterServiceImpl extends ServiceImpl<RouteFilterMapper, RouteFilterEntity> implements RouteFilterService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private RouteFilterMerchantMapper routeFilterMerchantMapper;

    @Autowired
    private RouteFilterMerchantService routeFilterMerchantService;

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO add(RouteFilterDO domain) {
        ResultDO result = new ResultSupport();
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        if(StringUtils.isEmpty(domain.getProviderId()) && StringUtils.isEmpty(domain.getMerchantId())){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }
        if(StringUtils.isNotEmpty(domain.getProviderId()) && (domain.getMerchantIds() == null || domain.getMerchantIds().isEmpty())){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }
        if(StringUtils.isNotEmpty(domain.getMerchantId()) && (domain.getProviderIds() == null || domain.getProviderIds().isEmpty())){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }

        //如果是供货商添加黑白名单
        if(StringUtils.isNotEmpty(domain.getProviderId())){
            RouteFilterEntity routeFilterEntity = new RouteFilterEntity();
            routeFilterEntity.setProviderId(domain.getProviderId());
            routeFilterEntity.setType(domain.getType());
            boolean res = false;
            try {
                res = this.save(routeFilterEntity);
            } catch(Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return result;
            }
            if(res){
              List<RouteFilterMerchantEntity> list = domain.getMerchantIds().stream().map( item -> {
                  RouteFilterMerchantEntity routeFilterMerchantEntity = new RouteFilterMerchantEntity();
                  routeFilterMerchantEntity.setRouteFilterId(routeFilterEntity.getId());
                  routeFilterMerchantEntity.setMerchantId(item);
                  return routeFilterMerchantEntity;
              }).collect(Collectors.toList());
                try {
                    res = routeFilterMerchantService.saveBatch(list);
                } catch(Exception e) {
                    result.setSuccess(false);
                    result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                    logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return result;
                }
                if(!res){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        } else if(StringUtils.isNotEmpty(domain.getMerchantId())){//如果是代理商添加黑白名单
            for (String item : domain.getProviderIds()){
                RouteFilterEntity routeFilterEntity = new RouteFilterEntity();
                routeFilterEntity.setProviderId(item);
                routeFilterEntity.setType(domain.getType());
                boolean res = false;
                try {
                    res = this.save(routeFilterEntity);
                } catch(Exception e) {
                    result.setSuccess(false);
                    result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                    logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return result;
                }
                if(res){
                    RouteFilterMerchantEntity routeFilterMerchantEntity = new RouteFilterMerchantEntity();
                    routeFilterMerchantEntity.setRouteFilterId(routeFilterEntity.getId());
                    routeFilterMerchantEntity.setMerchantId(domain.getMerchantId());
                    try {
                        res = routeFilterMerchantService.save(routeFilterMerchantEntity);
                    } catch(Exception e) {
                        result.setSuccess(false);
                        result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                        logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return result;
                    }
                    if(!res){
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    }
                }
            }
        }
        return result;
    }

    public ResultDO get(String id) {

        ResultDO result = new ResultSupport();
        RouteFilterEntity entity = null;

        try {
            entity = this.getById(id);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<RouteFilterMerchantEntity> list = null;
        try {
            list = routeFilterMerchantMapper.selectList(Wrappers.<RouteFilterMerchantEntity>lambdaQuery().eq(RouteFilterMerchantEntity::getRouteFilterId, id));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<RouteFilterMerchantDO> routeFilterMerchantList = getDomainRouteFilterMerchantList(list);

        RouteFilterDO domain = getDomain(entity);
        domain.setRouteFilterMerchanes(routeFilterMerchantList);
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }


    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResultDO remove(String id) {
        ResultDO result = new ResultSupport();

        RouteFilterEntity entity = new RouteFilterEntity();

        boolean res = false;
        try {
            res = this.removeById(id);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ROUTE_DELETE_FILTER_ERROR);
            logger.debug("error code：" + ErrorCode.ROUTE_DELETE_FILTER_ERROR.getCode() + " msg" + ErrorCode.ROUTE_DELETE_FILTER_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        try {
            res = routeFilterMerchantService.remove(Wrappers.<RouteFilterMerchantEntity>lambdaQuery().eq(RouteFilterMerchantEntity::getRouteFilterId, id));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ROUTE_DELETE_FILTER_ERROR);
            logger.debug("error code：" + ErrorCode.ROUTE_DELETE_FILTER_ERROR.getCode() + " msg" + ErrorCode.ROUTE_DELETE_FILTER_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        return result;
    }


    public ResultDO find(RouteFilterQueryDO query) {

        RouteFilterEntity entity = new RouteFilterEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, query);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        QueryWrapper<RouteFilterEntity> wrapper = new QueryWrapper<RouteFilterEntity>(entity);
        Page<RouteFilterEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        IPage<RouteFilterEntity> iPage = null;

        try {
            if(StringUtils.isNotEmpty(query.getMerchantName())){
                wrapper.lambda().like(RouteFilterEntity::getMerchantName, query.getMerchantName());
            }
            if(StringUtils.isNotEmpty(query.getProviderName())){
                wrapper.lambda().like(RouteFilterEntity::getProviderName, query.getProviderName());
            }
            if(StringUtils.isNotEmpty(query.getMerchantId())){
                wrapper.lambda().eq(RouteFilterEntity::getMerchantId, query.getMerchantId());
            }
            if(StringUtils.isNotEmpty(query.getProviderId())){
                wrapper.lambda().eq(RouteFilterEntity::getProviderId, query.getProviderId());
            }
            if(query.getType() != null){
                wrapper.eq("srf.type", query.getType());
            }
            iPage = baseMapper.selectOtherPage(page, wrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        List<RouteFilterDO> doList = getDomainList(iPage.getRecords());
        PageDO<RouteFilterDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }

    @Override
    public ResultDO findRouterByMerchantId(String merchantId, Integer routerType) {
        ResultDO result = new ResultSupport();
        if(StringUtils.isEmpty(merchantId) || routerType == null || (routerType != 1 && routerType != 2)){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }
        List<Map<String, Object>> list = null;
        try {
            list = baseMapper.findRouterByMerchantId(merchantId, routerType);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        if(list == null || list.isEmpty()){
            return result;
        }
        RouteFilterDO domain = new RouteFilterDO();
        domain.setMerchantId(merchantId);
        domain.setType(routerType);
        domain.setProviderIds(list.stream().map(m-> m.get("providerId").toString()).collect(Collectors.toList()));
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);
        return result;
    }

    @Override
    public ResultDO findRouterByProviderId(String providerId, Integer routerType) {
        ResultDO result = new ResultSupport();
        if(StringUtils.isEmpty(providerId) || routerType == null || (routerType != 1 && routerType != 2)){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }
        List<Map<String, Object>> list = null;
        try {
            list = baseMapper.findRouterByProviderId(providerId, routerType);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        if(list == null || list.isEmpty()){
            return result;
        }
        RouteFilterDO domain = new RouteFilterDO();
        domain.setProviderId(providerId);
        domain.setType(routerType);
        domain.setMerchantIds(list.stream().map(m-> m.get("merchantId").toString()).collect(Collectors.toList()));
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);
        return result;
    }

    public ResultDO getRouterByProviderAndMerchantId(String providerId, String merchantId, int type) {
        ResultDO result = new ResultSupport();
        long count = 0l;
        try {
            count = baseMapper.selectProviderAndMerchantCount(providerId, merchantId, type);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        if(count == 0) {
            result.setSuccess(true);
        } else {
            result.setSuccess(false);
        }
        return result;
    }

    private RouteFilterDO getDomain(RouteFilterEntity entity) {
        ResultDO result = new ResultSupport();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        RouteFilterDO domain = new RouteFilterDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<RouteFilterDO> getDomainList(List<RouteFilterEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<RouteFilterDO> doList = new ArrayList<RouteFilterDO>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(RouteFilterEntity entity : list) {

                RouteFilterDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }

    private RouteFilterMerchantDO getDomain(RouteFilterMerchantEntity entity) {

        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        RouteFilterMerchantDO domain = new RouteFilterMerchantDO();

        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<RouteFilterMerchantDO> getDomainRouteFilterMerchantList(List<RouteFilterMerchantEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<RouteFilterMerchantDO> doList = new ArrayList<RouteFilterMerchantDO>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(RouteFilterMerchantEntity entity : list) {

                RouteFilterMerchantDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
